package com.free.semantic.core.adaptor.impl;

import com.free.semantic.common.EqualFormula;
import com.free.semantic.common.ParamNode;
import com.free.semantic.common.RelationChain;
import com.free.semantic.common.RelationItem;
import com.free.semantic.core.ConceptInstanceManage;
import com.free.semantic.core.ConceptManage;
import com.free.semantic.core.FunctionProvider;
import com.free.semantic.core.RelationFunction;
import com.free.semantic.core.adaptor.ModelAdaptor;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 非嵌套
 */
public class ModelAdaptorImpl implements ModelAdaptor {


    private ConceptInstanceManage interfaceModel;

    private ConceptInstanceManage implementModel;

    private List<EqualFormula> equalFormulas = new ArrayList<>();

    /**
     * first到second的映射
     */
    private final Map<String, String> variableFirstToSecondMap = new HashMap<>();

    private final Map<String, String> variableSecondToFirstMap = new HashMap<>();

    @Override
    public void setInterfaceModel(ConceptInstanceManage interfaceModel) {
        this.interfaceModel = interfaceModel;
    }

    @Override
    public void setImplementModel(ConceptInstanceManage implementModel) {
        this.implementModel = implementModel;
    }

    @Override
    public void addEqualFormula(EqualFormula equalFormula) {
        equalFormulas.add(equalFormula);
        variableFirstToSecondMap.put(equalFormula.getLeftObjectName(), equalFormula.getRightObjectName());
        variableSecondToFirstMap.put(equalFormula.getRightObjectName(), equalFormula.getLeftObjectName());
    }

    @Override
    public FunctionProvider build() {
        Map<RelationItem, RelationFunction> functionMap = new HashMap<>();
        Set<String> modelObjLs = variableFirstToSecondMap.keySet();
        for (String firstFrom : modelObjLs) {

            for (String firstTo : modelObjLs) {
                if (firstFrom.equals(firstTo)) {
                    continue;
                }
                ConceptManage conceptManage = interfaceModel.concept();
                List<RelationItem> relation = conceptManage.getGoRelationByObject(firstFrom);
                List<RelationItem> filterItem = relation.stream().filter(item -> item.getDestObj().equals(firstTo)).collect(Collectors.toList());

                for (RelationItem relationItem : filterItem) {

                    boolean match = modelObjLs.containsAll(relationItem.getSourceObjList());
                    if (!match) {
                        continue;
                    }
                    if (!modelObjLs.contains(relationItem.getDestObj())) {
                        continue;
                    }
                    List<String> secondSourceMap = relationItem.getSourceObjList().stream().map(variableFirstToSecondMap::get).collect(Collectors.toList());

                    String secondDest = variableFirstToSecondMap.get(relationItem.getDestObj());
                    List<RelationChain> secondLs = implementModel.concept().findAllRelationChain(secondSourceMap, secondDest);

                    if (secondLs.size() > 1) {
                        throw new RuntimeException(String.format("关系：%s 无法在实现网络中找到唯一一条实现路径，请在接口模型中添加分支概念", relationItem));
                    }
                    functionMap.put(relationItem, context -> {
                        List<ParamNode> paramNodes = new ArrayList<>();
                        for (String s : relationItem.getSourceObjList()) {
                            String objName = variableFirstToSecondMap.get(s);
                            ParamNode paramNode = new ParamNode(objName, context.getListValue(s));
                            paramNodes.add(paramNode);
                        }
                        List<Object> value = implementModel.takePath(paramNodes, secondDest);
                        context.setValue(relationItem.getDestObj(), value);
                    });
                }

            }
        }
        return functionMap::get;
    }
}
